package com.niiwoo.civet.mobile.controller.refund;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.account.dto.common.UserAccountInfoDTO;
import com.niiwoo.civet.account.dto.response.AccountBaseResponse;
import com.niiwoo.civet.account.enums.AccountActiveEnum;
import com.niiwoo.civet.account.service.AccountDubboService;
import com.niiwoo.civet.base.constant.OrgConstant;
import com.niiwoo.civet.base.enums.OrderTradeSourceEnum;
import com.niiwoo.civet.base.enums.RefundTypeEnum;
import com.niiwoo.civet.mobile.util.R360RedisService;
import com.niiwoo.civet.mobile.vo.request.refund.OrgImmediateRepaymentRequestVO;
import com.niiwoo.civet.mobile.vo.request.refund.OrgQueryFullAmountRepaymentRequestVO;
import com.niiwoo.civet.mobile.vo.request.refund.OrgRepayRequestVO;
import com.niiwoo.civet.mobile.vo.response.fefund.OrgImmediateRepaymentResponseVO;
import com.niiwoo.civet.mobile.vo.response.fefund.OrgQueryFullAmountRepaymentReponseVO;
import com.niiwoo.civet.mobile.vo.response.fefund.RepayResponseVO;
import com.niiwoo.civet.trade.dto.request.RefundRequestDTO;
import com.niiwoo.civet.trade.dto.response.myloan.QueryFullAmountRepaymentReponseDTO;
import com.niiwoo.civet.trade.dto.response.newRefund.OrgImmediateRepaymentResponseDTO;
import com.niiwoo.civet.trade.service.myloan.MyLoanDubboService;
import com.niiwoo.civet.trade.service.newRefund.RefundDispatchDubboService;
import com.niiwoo.civet.trade.service.refund.RepaymentDubboService;
import com.niiwoo.civet.user.service.OrganizationDubboService;
import com.niiwoo.tripod.lanmao.enums.UserRoleEnum;
import com.niiwoo.tripod.web.annotation.AuthIgnore;
import com.niiwoo.tripod.web.vo.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.Objects;


@RestController
@RequestMapping("/orgRefund")
@Api(tags = "机构还款: (廖君君)", description = "/orgRefund")
@AuthIgnore
public class OrgRefundController {

    private static final Logger logger = LoggerFactory.getLogger(OrgRefundController.class);

    @Reference(version = "1.0.0")
    private RefundDispatchDubboService refundDispatchDubboService;

    @Reference(version = "1.0.0")
    private MyLoanDubboService myLoanDubboService;

    @Reference(version = "1.0.0")
    private RepaymentDubboService repaymentDubboService;

    @Reference(version = "1.0.0")
    private AccountDubboService accountDubboService;

    @Reference(version = "1.0.0")
    private OrganizationDubboService organizationDubboService;

    @Autowired
    private R360RedisService r360RedisService;

    @PostMapping("/repay")
    @ApiOperation("用户还款（廖君君）")
    public Result<RepayResponseVO> repay(@RequestBody @Valid OrgRepayRequestVO requestVO) {
        logger.info("OrgRefundController repay:requestVO={}", JSON.toJSON(requestVO));
        String userId = validThirdToken(requestVO.getToken(), requestVO.getChannel());
        logger.info("OrgRefundController repay:userId={}", userId);
        String orgId = getOrgId(requestVO.getChannel(), requestVO.getOrgCode());
        logger.info("OrgRefundController repay:orgId={}", orgId);
        RefundRequestDTO refundRequestDTO = new RefundRequestDTO();
        refundRequestDTO.setProjectId(requestVO.getProjectId());
        refundRequestDTO.setBorrowUserId(userId);
        refundRequestDTO.setRefundType(RefundTypeEnum.enumOf(requestVO.getRefundType()));
        refundRequestDTO.setOrderTradeSource(OrderTradeSourceEnum.APP);

        final RepayResponseVO responseVO = new RepayResponseVO();
        Long refundOrderId = refundDispatchDubboService.refund(refundRequestDTO);
        responseVO.setRefundOrderId(refundOrderId);
        return Result.with(responseVO);
    }

    @PostMapping("/immediateRepayment")
    @ApiOperation("立即还款弹窗查询（廖君君）")
    public Result<OrgImmediateRepaymentResponseVO> immediateRepayment(@RequestBody @Valid OrgImmediateRepaymentRequestVO requestVO) {
        logger.info("OrgRefundController immediateRepayment:requestVO={}", JSON.toJSON(requestVO));
        String userId = validThirdToken(requestVO.getToken(), requestVO.getChannel());
        logger.info("OrgRefundController immediateRepayment:userId={}", userId);
        String orgId = getOrgId(requestVO.getChannel(), requestVO.getOrgCode());
        logger.info("OrgRefundController immediateRepayment:orgId={}", orgId);
        OrgImmediateRepaymentResponseVO responseVO = new OrgImmediateRepaymentResponseVO();

        UserAccountInfoDTO userAccountInfoDTO = this.getAccount(userId, orgId);
        responseVO.setBorrowerActive(userAccountInfoDTO.getBorrowerActive());
        if (userAccountInfoDTO.getBorrowerActive().equals(AccountActiveEnum.UNACTIVATED.getValue())
                || userAccountInfoDTO.getBorrowerActive().equals(AccountActiveEnum.NOT_OPEN.getValue())) {
            return Result.with(responseVO);
        }

        responseVO.setBalanceAmountBorrower(userAccountInfoDTO.getBalanceAmountBorrower());
        responseVO.setBalanceAmountInvestor(userAccountInfoDTO.getBalanceAmountInvestor());

        OrgImmediateRepaymentResponseDTO orgImmediateRepaymentResponseDTO = myLoanDubboService.queryOrgImmediateRepayment(userId, orgId);
        BeanUtils.copyProperties(orgImmediateRepaymentResponseDTO, responseVO);
        if(Byte.valueOf("0").equals(responseVO.getStatus())){
            if(responseVO.getAmount().compareTo(responseVO.getBalanceAmountBorrower()) > 0){
                responseVO.setStatus(Byte.valueOf("1"));
            }
        }
        logger.info("OrgRefundController immediateRepayment:result={}", JSON.toJSON(responseVO));

        return Result.with(responseVO);
    }

    @PostMapping("/queryFullAmountRepayment")
    @ApiOperation("提前结清弹窗（廖君君）")
    public Result<OrgQueryFullAmountRepaymentReponseVO> queryFullAmountRepayment(
            @RequestBody @Valid OrgQueryFullAmountRepaymentRequestVO requestVO) {
        logger.info("OrgRefundController queryFullAmountRepayment:requestVO={}", JSON.toJSON(requestVO));
        String userId = validThirdToken(requestVO.getToken(), requestVO.getChannel());
        logger.info("OrgRefundController queryFullAmountRepayment:userId={}", userId);
        String orgId = getOrgId(requestVO.getChannel(), requestVO.getOrgCode());
        logger.info("OrgRefundController queryFullAmountRepayment:orgId={}", orgId);
        OrgQueryFullAmountRepaymentReponseVO responseVO = new OrgQueryFullAmountRepaymentReponseVO();

        UserAccountInfoDTO userAccountInfoDTO = this.getAccount(userId, orgId);

        if (userAccountInfoDTO.getBorrowerActive().equals(AccountActiveEnum.UNACTIVATED.getValue())
                || userAccountInfoDTO.getBorrowerActive().equals(AccountActiveEnum.NOT_OPEN.getValue())) {
            responseVO.setBorrowerActive(userAccountInfoDTO.getBorrowerActive());
            return Result.with(responseVO);
        }
        responseVO.setBalanceAmountBorrower(userAccountInfoDTO.getBalanceAmountBorrower());
        responseVO.setBalanceAmountInvestor(userAccountInfoDTO.getBalanceAmountInvestor());

        OrgImmediateRepaymentResponseDTO orgImmediateRepaymentResponseDTO = myLoanDubboService.queryOrgImmediateRepayment(userId, orgId);
        responseVO.setStatus(orgImmediateRepaymentResponseDTO.getStatus());
        if(Byte.valueOf("4").equals(responseVO.getStatus())){
            responseVO.setStatus(Byte.valueOf("0"));
        }

        if(Byte.valueOf("0").equals(responseVO.getStatus())){
            QueryFullAmountRepaymentReponseDTO dto = myLoanDubboService.queryFullAmountRepayment(orgImmediateRepaymentResponseDTO.getProjectId(), userId);
            BeanUtils.copyProperties(dto, responseVO);
            responseVO.setProjectId(orgImmediateRepaymentResponseDTO.getProjectId());
            if(responseVO.getRepaymentTotalAmount().compareTo(responseVO.getBalanceAmountBorrower()) > 0){
                responseVO.setStatus(Byte.valueOf("1"));
            }
        }
        logger.info("OrgRefundController queryFullAmountRepayment:result={}", JSON.toJSON(responseVO));

        return Result.with(responseVO);
    }

    private UserAccountInfoDTO getAccount(String userId, String orgId) {
        UserAccountInfoDTO accountInfoDTO = new UserAccountInfoDTO();
        AccountBaseResponse borrowAccount = null;
        AccountBaseResponse investorAccount = null;
        if (OrgConstant.NIIWOO_ORG_ID.equals(orgId)) {
            borrowAccount = accountDubboService.getNiiwooAccount(userId, UserRoleEnum.BORROWERS);
            investorAccount = accountDubboService.getNiiwooAccount(userId, UserRoleEnum.INVESTOR);
        } else {
            borrowAccount = accountDubboService.getOrgAccount(userId, orgId);
        }
        if (Objects.nonNull(borrowAccount)) {
            accountInfoDTO.setAccountNoBorrower(borrowAccount.getAccountNo());
            accountInfoDTO.setBorrowerActive(borrowAccount.getImportUserActiva());
            accountInfoDTO.setBalanceAmountBorrower(borrowAccount.getAvailableAmount());
        }
        if (Objects.nonNull(investorAccount)) {
            accountInfoDTO.setIsFreeInvest(investorAccount.getTender());
            accountInfoDTO.setAccountNoInvestor(investorAccount.getAccountNo());
            accountInfoDTO.setInvestorActive(investorAccount.getImportUserActiva());
            accountInfoDTO.setBalanceAmountInvestor(investorAccount.getAvailableAmount());
        }
        return accountInfoDTO;
    }

    /**
     * 验证第三方TOKEN，获取userId
     *
     * @param token
     * @param channel
     * @return
     */
    private String validThirdToken(String token, Integer channel) {
        String userId;
        if (channel == null) {
            userId = r360RedisService.verifyTokenAndGetUserId(token);
        } else {
            userId = r360RedisService.verifyTokenAndGetUserId(token, channel);
        }
        return userId;
    }

    /**
     * 获取orgId
     *
     * @param channel
     * @param orgCode
     * @return
     */
    private String getOrgId(Integer channel, String orgCode) {
        String orgId = OrgConstant.NIIWOO_ORG_ID;

        if (Objects.equals(R360RedisService.ThirdPart.ORG.getChannel(), channel)) {
            orgId = organizationDubboService.loadValidOrgId(orgCode);
        }
        return orgId;
    }

}
